package optimizer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class Tracker {

	private Map<Register,Integer> registryLock;
	private int clockcycle;
	private Instruction ins;

	Tracker(int startingClockCycle) {
		this.clockcycle = startingClockCycle;
		this.registryLock = new HashMap<Register,Integer>();
		this.ins = new Instruction (null, "STALL", null, null, null, -1, null,"");
	}

	void setRegisterLock(Register r, int period){
		if(r == null)
			return;
		if(this.registryLock.containsKey(r)) {
			//System.out.println("Warning: Possible overlaping of write operations on register '"+r+"'");
			if(this.registryLock.get(r)<period) {
				this.registryLock.put(r, period);
			}
			else {
				;//System.out.println("Warning: Possibility of occuring WAW haddard");				
			}

		}
		else {
			this.registryLock.put(r, period);
		}

	}
	
	ArrayList<Register> getDependencies() {
		ArrayList<Register> dependencylist = new ArrayList<Register>();
		
		Iterator i = this.registryLock.entrySet().iterator();
		while(i.hasNext()) { 
			Map.Entry me = (Map.Entry)i.next();
			if((Integer)me.getValue()>=1) {
				dependencylist.add((Register)me.getKey());
			}
			else {
				;//System.out.println("Error: Tracker.getDependencies(): Invalide dependency listed in tracker");
			}
		} 
		
		return dependencylist;
	}

	void printTracker(String prefix){
		Iterator i = this.registryLock.entrySet().iterator(); 

		while(i.hasNext()) { 
			Map.Entry me = (Map.Entry)i.next(); 
			//System.out.println(prefix + me.getKey() + ": " + me.getValue()); 
		} 
	}

	void runClockPulse(Instruction ins){
		this.ins = ins;
		this.clockcycle++;
		
		Map<Register,Integer> newRegistryLock = new HashMap<Register, Integer>();
		
		Set<Register> keySet = this.registryLock.keySet();		
		Iterator<Register> i = keySet.iterator();
		while(i.hasNext()) { 
			Register currentRegister = (Register)i.next();
			int currentRegistorPeriod = this.registryLock.get(currentRegister);

			if(currentRegistorPeriod>1) {
				newRegistryLock.put(currentRegister, currentRegistorPeriod-1);
				//System.out.println(me.getKey() + ": " + me.getValue());
			}
//			else {
//				this.registryLock.remove(currentRegister);
//			}
		}
		
		this.registryLock = newRegistryLock;
	}

	boolean isRegisterLock(Register r){
		if(r==null) return false;
		//if(!this.registryLock.containsKey(r)) System.out.println("Register : " + r + " does not contains on Registry Lock");
		return this.registryLock.containsKey(r);
	}

	int getClockcycle() {
		return clockcycle;
	}

	Instruction getIns() {
		return this.ins;
	}
}
